package ar.edu.unlp.info.tesis.domain;

import java.util.Date;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.persistence.Transient;

import org.codehaus.jackson.annotate.JsonIgnore;
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
import org.codehaus.jackson.annotate.JsonTypeName;
import org.hibernate.annotations.Any;
import org.hibernate.annotations.AnyMetaDef;
import org.hibernate.annotations.MetaValue;

/**
 * 
 * https://github.com/adlnet/xAPI-Spec/blob/master/xAPI.md#stmtprops
 * 
 */

@Entity
@Table(name = "Statement")
@DiscriminatorValue(value = "STATEMENT")
@JsonTypeName("STATEMENT")
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
public class Statement extends Entidad implements StatementObject {

	private long dataBaseId;
	
	private String id;

	private Actor actor;

	private Verb verb;

	// Puede ser una actividad, un actor (tipo agente) u otro statement
	private StatementObject object;

	private Result result;

	private Context context;

	private Date timestamp;

	private Date stored;

	private Actor authority;

	private List<Attachment> attachments;
	
	private String originalJSON;
	
	@Id
	@GeneratedValue
	@JsonIgnore
	@Column(name = "DATABASEID")
	public long getDataBaseId() {
		return dataBaseId;
	}
	
	public void setDataBaseId(long dataBaseId) {
		this.dataBaseId = dataBaseId;
	}

	@Column(name = "ID")
	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	@ManyToOne
	@JoinColumn(name = "ACTOR_ID", nullable = false)
	public Actor getActor() {
		return actor;
	}

	public void setActor(Actor actor) {
		this.actor = actor;
	}

	@ManyToOne
	@JoinColumn(name = "VERB_ID", nullable = false)
	public Verb getVerb() {
		return verb;
	}

	public void setVerb(Verb verb) {
		this.verb = verb;
	}

	@Any(metaColumn = @Column(name="OBJECTTYPE"))
	@AnyMetaDef(idType = "long", metaType = "string",
	metaValues = {
	@MetaValue(targetEntity = Agent.class, value = "AGENT"),
	@MetaValue(targetEntity = Group.class, value = "GROUP"),
	@MetaValue(targetEntity = Activity.class, value = "ACTIVITY"),
	@MetaValue(targetEntity = Statement.class, value = "STATEMENT"),
	@MetaValue(targetEntity = StatementRef.class, value = "STATEMENTREF")
	})
	@JoinColumn(name="OBJECT_ID")
	public StatementObject getObject() {
		return object;
	}

	public void setObject(StatementObject object) {
		this.object = object;
	}

	@OneToOne
	@JoinColumn(name = "RESULT_ID")
	public Result getResult() {
		return result;
	}

	public void setResult(Result result) {
		this.result = result;
	}
	
	@OneToMany
	@JoinColumn(name = "STATEMENT_ID")
	public List<Attachment> getAttachments() {
		return attachments;
	}

	public void setAttachments(List<Attachment> attachments) {
		this.attachments = attachments;
	}


	@OneToOne(cascade=CascadeType.ALL)
	@JoinColumn(name = "CONTEXT_ID", nullable= true)
	public Context getContext() {
		return context;
	}

	public void setContext(Context context) {
		this.context = context;
	}

	@Column(name = "TIMESTAMP")
	public Date getTimestamp() {
		return timestamp;
	}

	public void setTimestamp(Date timestamp) {
		this.timestamp = timestamp;
	}

	@Column(name = "STORED")
	public Date getStored() {
		return stored;
	}

	public void setStored(Date stored) {
		this.stored = stored;
	}

	@ManyToOne
	@JoinColumn(name = "AUTHOR_ID")
	public Actor getAuthority() {
		return authority;
	}

	public void setAuthority(Actor authority) {
		this.authority = authority;
	}
	
	@JsonIgnore
	@Column(name = "ORIGINALJSON")
	public String getOriginalJSON() {
		return originalJSON;
	}
	
	public void setOriginalJSON(String originalJSON) {
		this.originalJSON = originalJSON;
	}

	@Override
	@Transient
	public String getObjectType() {
		return StatementObject.STATEMENT;
	}

	@Override
	@Transient
	public String getLabelFormat() {
		return this.getActor().getLabelFormat() + " - " + this.getObject().getLabelFormat();
	}
}
